# encoding: utf-8
"""
@author: youfeng
@file: proxy_lock_dao.py
@time: 2018/8/14 下午10:47
"""

# 代理存储管理
import time

import redis

from dao.redis_lock import RedisLock


class ProxyLockDAO(object):
    # 锁关键字
    __LOCK_KEY = "proxy_lock"

    # 代理列表关键字
    __PROXY_LIST_KEY = "proxy:list:"

    def __init__(self, redis_conf, log=None):
        self.log = log

        # 初始化redis
        self.__redis_handler = redis.StrictRedis(host=redis_conf['host'],
                                                 port=redis_conf['port'],
                                                 db=redis_conf['db'],
                                                 password=redis_conf['password'],
                                                 max_connections=redis_conf['max_connections'])
        # 初始化redis 锁
        self.__lock = RedisLock(self.__redis_handler, log)

    # 获得代理redis主键
    def __get_proxy_list_key(self, tag):
        return "{}{}".format(self.__PROXY_LIST_KEY, tag)

    # 根据redis主键获得标签
    def __get_proxy_list_tag(self, key):
        return key.replace(self.__PROXY_LIST_KEY, "")

    # 删除所有代理
    def __delete_all_proxy(self):
        start_time = time.time()
        key_list = self.__redis_handler.keys(self.__get_proxy_list_key("*"))
        for key in key_list:
            self.log.info("当前删除代理: {}".format(key))
            self.__redis_handler.delete(key)
        self.log.info("删除存储在redis的代理耗时: {} s".format(round(time.time() - start_time, 2)))

    def __save_all_proxy(self, proxy_list_dict):

        start_time = time.time()
        pipe = self.__redis_handler.pipeline()
        for tag, proxy_list in proxy_list_dict.iteritems():
            redis_key = self.__get_proxy_list_key(tag)

            sort_list = sorted(proxy_list)

            # 再存储列表到redis
            for proxy in sort_list:
                pipe.rpush(redis_key, proxy)
        result = pipe.execute()
        self.log.info("存储代理耗时: {} s".format(round(time.time() - start_time, 2)))

    # 获得全部代理
    def __get_all_proxy(self):
        proxy_list_dict = {}
        start_time = time.time()
        key_list = self.__redis_handler.keys(self.__get_proxy_list_key("*"))
        for key in key_list:
            try:
                self.log.info("当前获取代理: {}".format(key))
                proxy_list = self.__redis_handler.lrange(key, 0, -1)
                tag = self.__get_proxy_list_tag(key)
                proxy_list_dict[tag] = proxy_list
            except Exception as e:
                self.log.error("获取redis中代理异常: key = {}".format(key))
                self.log.exception(e)
        self.log.info("获取代理耗时: {} s".format(round(time.time() - start_time, 2)))

        return proxy_list_dict

    # 存储代理
    def set_proxy(self, proxy_list_dict):

        is_success = False

        if not isinstance(proxy_list_dict, dict):
            return is_success

        if len(proxy_list_dict) <= 0:
            return is_success

        start_time = time.time()

        try:
            # 先加锁
            self.__lock.lock(self.__LOCK_KEY)

            # 先删除之前存储的代理
            self.__delete_all_proxy()

            # 存储所有代理
            self.__save_all_proxy(proxy_list_dict)

            is_success = True
        except Exception as e:
            self.log.error("proxy 存储到redis失败:")
            self.log.exception(e)
        finally:
            self.__lock.release(self.__LOCK_KEY)

        self.log.info("存储代理到redis总耗时: {} s".format(round(time.time() - start_time, 2)))
        return is_success

    # 提取代理列表
    def get_proxy(self):
        start_time = time.time()
        try:
            # 先加锁
            self.__lock.lock(self.__LOCK_KEY)
            proxy_list_dict = self.__get_all_proxy()
        except Exception as e:
            self.log.error("获取redis 中代理失败:")
            self.log.exception(e)
            proxy_list_dict = {}
        finally:
            self.__lock.release(self.__LOCK_KEY)

        self.log.info("从redis中提取代理耗时: {} s".format(round(time.time() - start_time, 2)))
        return proxy_list_dict
